﻿using mozhi.smarterp.Finance.Accounts.Repository;
using mozhi.smarterp.Finance.Basedatas.Services;
using mozhi.smarterp.Finance.Basedatas;
using mozhi.smarterp.Finance.Finances.Repository;
using mozhi.smarterp.Finance.Finances.Services;
using mozhi.smarterp.Finance.Querys;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Guids;
using mozhi.smarterp.Finance.Files.Services;
using Mozhi.Abp.Core.Extensions;
using Mozhi.Abp.Domain.BasicData.Repositories;

namespace mozhi.smarterp.Finance.Finances
{
    public class JournalAppService : FinanceAppService, IJournalAppService
    {
        private IJournalRepository _repository;
        private JournalManager _journalManager;
        private IGuidGenerator _guidGenerator;
        private IAccountRepository _accountRepository;
        private DimensionGroupValueManager _dimensionGroupValueManager;
        private IJournalNumberPrefixRepository _journalNumberPrefixRepository;
        private AttachmentManager _attachmentManager;

        public JournalAppService(IJournalRepository repository, JournalManager journalManager, IGuidGenerator guidGenerator,
            IAccountRepository accountRepository, DimensionGroupValueManager dimensionGroupValueManager, AttachmentManager attachmentManager,
            IOrganizationRepository organizationRepository, IJournalNumberPrefixRepository journalNumberPrefixRepository) : base(organizationRepository)
        {
            _repository = repository;
            _journalManager = journalManager;
            _guidGenerator = guidGenerator;
            _accountRepository = accountRepository;
            _dimensionGroupValueManager = dimensionGroupValueManager;
            _journalNumberPrefixRepository = journalNumberPrefixRepository;
            _attachmentManager = attachmentManager;
        }

        public async Task<PagedResultDto<JournalDto>> FindAsync(JournalPageQuery query)
        {
            var journals = await _repository.FindAsync(query);

            var count = await _repository.GetCountAsync(query);

            var result = new PagedResultDto<JournalDto>();

            var dtos = ObjectMapper.Map<List<Journal>, List<JournalDto>>(journals);

            await LoadOtherInfoAsync(dtos);

            result.TotalCount = count;
            result.Items = dtos;

            return result;
        }

        public async Task<JournalDto> GetAsync(Guid id)
        {
            var journal = await _repository.FindAsync(id, true);

            var dto = ObjectMapper.Map<Journal, JournalDto>(journal);

            await LoadOtherInfoAsync(new List<JournalDto> { dto });

            return dto;
        }

        public async Task<JournalDto> CreateAsync(JournalCreateDto dto)
        {
            //var organization = await GetOrganizationAsync();

            //organization.ValidateFinance();

            //if (dto.Items == null || dto.Items.Count == 0)
            //    throw new UserFriendlyException("凭证分录不能为空", "100000");

            //var journal = await _journalManager.Create(_guidGenerator.Create(), dto.NumberPrefixId, dto.Date);

            //var accountIds = dto.Items.Select(x => x.AccountId).Distinct().ToList();

            //var accounts = await _accountRepository.FindAsync(new AccountQuery() { IncludeDetail = true, Ids = accountIds });

            //var journalItems = new List<JournalItem>();

            //foreach (var item in dto.Items)
            //{
            //    var account = accounts.FirstOrDefault(x => x.Id == item.AccountId);

            //    item.DimensionGroupValueItems = item.DimensionGroupValueItems == null ? null : item.DimensionGroupValueItems.Where(x => !x.Value.IsNullOrEmpty()).ToList();

            //    await _dimensionGroupValueManager.ValidateDimensionGroupValue(account.DimensionItems, GetDimensionGroupValueItems(item.DimensionGroupValueItems));
            //    //带核算维度，币别的余额
            //    var dimensionItemsQuery = ObjectMapper.Map<List<DimensionGroupValueItemDto>, List<DimensionGroupValueItemQuery>>(item.DimensionGroupValueItems);
            //    var dimensionGroupValueId = await _dimensionGroupValueManager.GetDimensionGroupValueId(new DimensionGroupValuePageQuery() { Items = dimensionItemsQuery, PageIndex = 1, PageSize = 1 });

            //    item.CurrencyId = item.CurrencyId ?? organization.StandardCurrencyId;

            //    item.ExchangeRate = organization.StandardCurrencyId == item.CurrencyId ? 1 : item.ExchangeRate;

            //    var journalItem = new JournalItem(_guidGenerator.Create(), item.Summary, item.AccountId, item.Direction, dimensionGroupValueId,
            //        item.CurrencyId.Value, item.ExchangeRate ?? 1, item.AmountFr, item.DebitAmount, item.CreditAmount, item.Index);

            //    journalItems.Add(journalItem);
            //}

            //await _journalManager.ChangeItems(journal, journalItems);

            //journal = await _repository.InsertAsync(journal);

            //var journalDto = ObjectMapper.Map<Journal, JournalDto>(journal);

            //await LoadOtherInfoAsync(new List<JournalDto> { journalDto });

            //return journalDto;
            throw new NotImplementedException();
        }


        public async Task<JournalDto> UpdateAsync(JournalUpdateDto dto)
        {
            //var organization = await GetOrganizationAsync();

            //organization.ValidateFinance();

            //var journal = await _repository.GetAsync(dto.Id);

            //if (journal == null)
            //    throw new UserFriendlyException("凭证不存在", "100000");

            //if (dto.Items == null || dto.Items.Count == 0)
            //    throw new UserFriendlyException("凭证分录不能为空", "100000");

            //var accountIds = dto.Items.Select(x => x.AccountId).Distinct().ToList();

            //var accounts = await _accountRepository.FindAsync(new AccountQuery() { IncludeDetail = true, Ids = accountIds });

            //var journalItems = new List<JournalItem>();

            //foreach (var item in dto.Items)
            //{
            //    var account = accounts.FirstOrDefault(x => x.Id == item.AccountId);

            //    item.DimensionGroupValueItems = item.DimensionGroupValueItems == null ? null : item.DimensionGroupValueItems.Where(x => !x.Value.IsNullOrEmpty()).ToList();

            //    await _dimensionGroupValueManager.ValidateDimensionGroupValue(account.DimensionItems, GetDimensionGroupValueItems(item.DimensionGroupValueItems));
            //    //带核算维度，币别的余额
            //    var dimensionItemsQuery = ObjectMapper.Map<List<DimensionGroupValueItemDto>, List<DimensionGroupValueItemQuery>>(item.DimensionGroupValueItems);
            //    var dimensionGroupValueId = await _dimensionGroupValueManager.GetDimensionGroupValueId(new DimensionGroupValuePageQuery() { Items = dimensionItemsQuery, PageIndex = 1, PageSize = 1 });

            //    item.CurrencyId = item.CurrencyId ?? organization.StandardCurrencyId;

            //    item.ExchangeRate = organization.StandardCurrencyId == item.CurrencyId ? 1 : item.ExchangeRate;

            //    var journalItem = new JournalItem(_guidGenerator.Create(), item.Summary, item.AccountId, item.Direction, dimensionGroupValueId,
            //        item.CurrencyId.Value, item.ExchangeRate ?? 1, item.AmountFr, item.DebitAmount, item.CreditAmount, item.Index);

            //    journalItems.Add(journalItem);
            //}

            //await _journalManager.ChangeItems(journal, journalItems);

            //journal = await _repository.UpdateAsync(journal);

            //var journalDto = ObjectMapper.Map<Journal, JournalDto>(journal);

            //await LoadOtherInfoAsync(new List<JournalDto> { journalDto });

            //return journalDto;
            throw new NotImplementedException();
        }

        public async Task<bool> DeleteAsync(Guid id)
        {
            //var journal = await _repository.GetAsync(id);

            //if (journal == null)
            //    throw new UserFriendlyException("凭证不存在", "100000");

            //if (journal.Approved == true)
            //    throw new UserFriendlyException("凭证已审核，不允许删除", "100000");

            //await _repository.DeleteAsync(id);

            //return true;
            throw new NotImplementedException();
        }

        public async Task<bool> ApproveAsync(Guid id, bool approved)
        {
            var journal = await _repository.GetAsync(id);

            if (journal == null)
                throw new UserFriendlyException("凭证不存在", "100000");

            var organization = await GetOrganizationAsync();
            organization.ValidateFinance();

            await _journalManager.ValidateSettlement(new List<int>() { journal.Period });

            journal.ChangeApproveStatus(approved);

            await _repository.UpdateAsync(journal);

            return true;
        }

        public async Task<string> GetNextNumberAsync(Guid numberPrefixId, int period)
        {
            var result = await _journalManager.GetNextJournalNumber(numberPrefixId, period);

            return result;
        }

        public async Task<int> GetCountAsync( int? period)
        {
            var result = await _repository.GetCountAsync(new JournalPageQuery() { Period = period});

            return result;
        }

        #region
        private async Task LoadOtherInfoAsync(List<JournalDto> journals)
        {
            //if (journals == null || journals.Count == 0)
            //    return;


            //var numberPrefixIds = journals.Where(x => x.NumberPrefixId.HasValue).Select(x => x.NumberPrefixId.Value).Distinct().ToList(); ;

            //var journalNumberPrefixs = await _journalNumberPrefixRepository.FindAsync(new PageQuery() { PageIndex = 1, PageSize = int.MaxValue, Ids = numberPrefixIds });

            //var accountIds = journals.Select(x=>x.Items).ToList().Join().Select(x=>x.AccountId).Distinct().ToList();

            //var accounts = await _accountRepository.FindAsync(new AccountQuery() { Ids = accountIds });

            //foreach (var journal in journals)
            //{
            //    var matchNumberPrefix = journalNumberPrefixs.FirstOrDefault(x => x.Id == journal.NumberPrefixId);

            //    journal.FullNumber = matchNumberPrefix?.Name + "-" + journal.Number;
            //    journal.NumberPrefix = matchNumberPrefix?.Name;

            //    foreach (var item in journal.Items)
            //    {
            //        var matchAccount = accounts.FirstOrDefault(x => x.Id == item.AccountId);

            //        item.AccountFullName = matchAccount?.FullName;
            //    }
            //}
            throw new NotImplementedException();
        }

        #endregion
    }
}
